package chen.web.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.Swap;

public class OperationSystemInfoProvider implements Runnable{
	
	private static List<OperationSystemInfo> OperationSystemInfoList = Collections.synchronizedList(new LinkedList<OperationSystemInfo>());
	
	private static final Log log = LogFactory.getLog(OperationSystemInfoProvider.class);
	
	private static int Period;
	private static int ContainerSize;
	private static long LastOpertionTimestamp;
	
	static{
		init();
	}

	/**
	 * 设置更新信息的时间间隔, 默认是2000毫秒
	 * @param period
	 */
	public static void setPeriod(int period){
		OperationSystemInfoProvider.Period = period;
	}
	
	/**
	 * 设置保存信息的容器大小. 默认保存20条信息
	 * 该参数与时间间隔配合使用.
	 * @param size
	 */
	public static void setContainerSize(int size){
		ContainerSize = size;
	}
	
	/**
	 * 获取系统信息列表, 参数startTime表示从何时间点开始获取. 
	 * 此方法会在启动一个线程, 定时更新数据到内部的容器中. 
	 * 内部容器的大小是固定的, 当容器填满后, 会删除最旧的并且读取过的的数据.
	 * 当容器中填满并且信息全部是没有获取过的新信息, 则线程会停止直到下次调用此方法.
	 * 如果容器中的信息时间都小于指定参数的时间点, 则返回一个空的list
	 * @param startTime		开始时间
	 * @return
	 */
	public static List<OperationSystemInfo> getOperationSystemInfoList(long startTime){
		if(!start){		//容器是空的, 还未开始获取信息
			synchronized(OperationSystemInfoProvider.class){
				if(!start){
					OperationSystemInfoProvider provider = new OperationSystemInfoProvider();
					Thread thread = new Thread(provider);
					thread.start();
					while(!start || OperationSystemInfoList.size()==0){}
				}
			}
		} 
		
		List<OperationSystemInfo> result = new ArrayList<OperationSystemInfo>();
		for(OperationSystemInfo info : OperationSystemInfoList){
			if(info.getTimestamp() > startTime){
				result.add(info);
				LastOpertionTimestamp = info.getTimestamp();
			}
		}
		return result;
	}
	
	/**
	 * 初始化变量
	 */
	private static void init(){
		start = false;
		Period = 2000;
		ContainerSize = 20;
		LastOpertionTimestamp = 0;
	}
	
	
	private static boolean start;
	/**
	 * 开始获取信息
	 */
	private static void start(){
		start = true;
		l1 :while(start){
			OperationSystemInfo info = getOperationSystemInfo();
			while(OperationSystemInfoList.size() >= ContainerSize){
				OperationSystemInfo removedInfo = OperationSystemInfoList.remove(0);
				//当要删掉的info的时间截大于上次获取信息的时间截, 表示容器中全部是没有获取过的新信息, 停止更新.
				if(LastOpertionTimestamp != 0 && removedInfo.getTimestamp() > LastOpertionTimestamp){
					break l1;
				}
			}
			OperationSystemInfoList.add(info);
			if(log.isDebugEnabled()){
				log.debug("记录当前系统信息到容器中");
			}
			try {
				Thread.sleep(Period);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				log.error("出错", e);
				init();
			}
		}
		init();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		start();
	}
	
	private static Sigar sigar = new Sigar();
	/**
	 * 获取当前时间点的系统信息
	 * @return
	 */
	public static OperationSystemInfo getOperationSystemInfo(){
		OperationSystemInfo info = new OperationSystemInfo();
		try {
			Mem mem = sigar.getMem();
			info.totalPhysicalMemorySize = mem.getTotal();
			info.freePhysicalMemorySize = mem.getFree();
			
			Swap swap = sigar.getSwap();
			info.totalSwapSpaceSize = swap.getTotal();
			info.freeSwapSpaceSize = swap.getFree();
			
			CpuPerc[] cpuList = sigar.getCpuPercList();
			double cpuIdle = 0;
			double cpuWait = 0;
			for(CpuPerc cpu : cpuList){
				cpuIdle = cpuIdle + cpu.getIdle();
				cpuWait = cpuWait + cpu.getWait();
			}
			info.cpuUsedPercent = 1 - cpuIdle/cpuList.length;
			info.cpuWaitPercent = cpuWait/cpuList.length;
			
		} catch (SigarException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
		return  info;
	}
	

	public static void main(String[] args) throws Exception{
		OperationSystemInfo info = OperationSystemInfoProvider.getOperationSystemInfo();
		System.out.println(info.getCpuWaitPercent());
	}
	
	public static class OperationSystemInfo{
		private long timestamp;		//时间截
		private long totalPhysicalMemorySize;	//总的物理内存
		private long freePhysicalMemorySize;		//剩余的物理内存
		private long totalSwapSpaceSize;			// 交换区总量
		private long freeSwapSpaceSize;			//交换区使用量
		
		private double cpuUsedPercent;			//cpu使用率
		private double cpuWaitPercent;			//cpu等待

		private long netSpeed;

		private OperationSystemInfo(){
			this.timestamp = System.currentTimeMillis();
		}
		
		
		public long getTimestamp() {
			return timestamp;
		}

		public long getTotalPhysicalMemorySize() {
			return totalPhysicalMemorySize;
		}

		public long getFreePhysicalMemorySize() {
			return freePhysicalMemorySize;
		}

		public long getTotalSwapSpaceSize() {
			return totalSwapSpaceSize;
		}

		public long getFreeSwapSpaceSize() {
			return freeSwapSpaceSize;
		}

		public double getCpuUsedPercent() {
			return cpuUsedPercent;
		}

		public long getNetSpeed() {
			return netSpeed;
		}
		public double getCpuWaitPercent() {
			return cpuWaitPercent;
		}
	}
}
